package top.mengchaob.fileserver.netty;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.AttributeKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import top.mengchaob.fileserver.netty.bean.ResultBeanNetty;
import top.mengchaob.fileserver.netty.busAtomHandler.*;
import top.mengchaob.fileserver.netty.handler.HttpResponseEncoderMC;
import top.mengchaob.fileserver.netty.handler.ParaChannelHandler;
import top.mengchaob.fileserver.netty.handler.ResourceHander;
import top.mengchaob.fileserver.netty.handler.UploadEncoder;
import top.mengchaob.fileserver.netty.util.OPTFILE;
import top.mengchaob.util.SpringCtx;

import java.util.HashMap;

/**
 * @author ：mengchao
 * @date ：Created in 2019/9/19 11:12
 * @description：处理链接请求
 */
public class HttpServer extends SimpleChannelInboundHandler<HttpObject> {

    private static final Logger logger = LoggerFactory.getLogger(HttpServer.class);
    private static final AttributeKey<ResultBeanNetty> RESULTBEAN = AttributeKey.valueOf("resultBean");
    private String method = "";
    /**
     * 默认为自动释放资源
     */
    public HttpServer(){
        super();
    }

    /**
     * autoRelease 为true时自动释放资源
     * @param autoRelease
     */
    public HttpServer(boolean autoRelease){
        super(autoRelease);
    }
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject httpObject) throws Exception {
        if (httpObject instanceof HttpRequest) {
            HttpRequest request = (HttpRequest)httpObject;
            this.method = request.method().name();
        }
        if (httpObject instanceof HttpContent) {
            ParaChannelHandler paraChannelHandler = (ParaChannelHandler) ctx.pipeline().get("paraChannelHandler");
            HashMap<String, String> formPara = paraChannelHandler.formaras;
            HashMap<String, String> header = paraChannelHandler.headers;
            HashMap<String, String> urlParas = paraChannelHandler.urlParas;
            String type = urlParas.get("type");
            if("GET".equals(this.method) && type ==null){//下载使用
                HttpContent chunk = (HttpContent) httpObject;
                //接受完最后一个数据块之后进行处理
                if(chunk instanceof LastHttpContent) {
                    //由于文件下载使用response,所以需要添加response编码器 ,删除resourceHander
                    if (ctx.pipeline().get("httpResponseEncoder") == null) {
                        ctx.pipeline().addAfter(ctx.name(), "httpResponseEncoder", new HttpResponseEncoder());
                    }
                    if (ctx.pipeline().get("chunkedWriteHandler") == null) {
                        ctx.pipeline().addAfter("httpResponseEncoder", "chunkedWriteHandler", new ChunkedWriteHandler());
                    }
                    if (ctx.pipeline().get("httpDownFileServerHandler") == null) {
                        ctx.pipeline().addAfter("chunkedWriteHandler", "httpDownFileServerHandler", new HttpDownFileServerHandler());
                    }
                }
                logger.debug("添加下载文件httpDownFileServerHandler");
            }else{//http上传文件使用
                HttpContent chunk = (HttpContent) httpObject;
                String tmpName="";
                //接受完最后一个数据块之后进行处理
                if(chunk instanceof LastHttpContent) {
                    ctx.pipeline().addAfter("httpServer","resourceHander",new ResourceHander());
                    String optType = formPara.get("optType");
                    ResultBeanNetty resultBean = new ResultBeanNetty();
                    //根据不同的路径添加删除不同的channelHandler
                    if (OPTFILE.DELFILE.getoptType().equals(optType)) {
                        resultBean.setOptType(OPTFILE.DELFILE.getoptType());
                        Object delFileAtomHandler = SpringCtx.getTByName("delFileAtomHandler");
                        tmpName = "delFileAtomHandler";
                        ctx.pipeline().addAfter("httpServer", tmpName, (DelFileAtomHandler)delFileAtomHandler);
                        logger.debug("添加删除文件channelHandler");
                    } else if (OPTFILE.ADDFILE.getoptType().equals(optType)) {
                        resultBean.setOptType(OPTFILE.ADDFILE.getoptType());
                        Object saveFileAtomHandlerObj = SpringCtx.getTByName("saveFileAtomHandler");
                        tmpName = "saveFileAtomHandler";
                        ctx.pipeline().addAfter("httpServer", tmpName, (SaveFileAtomHandler)saveFileAtomHandlerObj);
                        logger.debug("添加保存文件channelHandler");
                    } else if (OPTFILE.COVERFILE.getoptType().equals(optType)) {
                        resultBean.setOptType(OPTFILE.COVERFILE.getoptType());
                        logger.debug("文件转换功能暂未开发");
                    } else if(OPTFILE.UPDATE.getoptType().equals(optType)){
                        resultBean.setOptType(OPTFILE.UPDATE.getoptType());
                        Object updateFileAtomHandler = SpringCtx.getTByName("updateFileAtomHandler");
                        tmpName = "updateFileAtomHandler";
                        ctx.pipeline().addAfter("httpServer", tmpName, (UpdateFileAtomHandler)updateFileAtomHandler);
                        logger.debug("更新文件channelHandler");
                    } else {
                        resultBean.setOptType("optType");
                        throw new Exception("不存在的操作类型!");
                    }
                    /**
                     * 打印响应结果
                     */
                    ctx.pipeline().addAfter(tmpName, "responseHandler", new ResponseHandler());
//                    ctx.pipeline().addLast("uploadEncoder",new UploadEncoder());
                    ctx.channel().attr(RESULTBEAN).setIfAbsent(resultBean);
                }

            }
            ctx.fireChannelRead(httpObject);
        }
    }
}
